local __class = {}
function __class:__call(...)
	-- this is the classes constructor called like so
	-- className() the call meta-method allows us to call 
	-- a table like a function so I use this as the constructor
	
	-- make a new table
	local c = table.Copy(self)
	setmetatable(c,c.mt) -- set the meta table of this new table this is what makes it a class
	c.instance = true -- tell this table its an instance of the base class
	
	--the line below is just a hack of saying if the constructor of the class doesnt exist
	--then use an empty function and call that
	local func = (c.new or function() end)(c, ...)
	return c
end

function __class:__index(k)
	-- if the index method cant find a variable in the table itself
	-- we check the base class table of this table for the variable
	-- and return that
	local ret = self.base[k]
	-- if we didnt find a local variable then check the static variables
	if not ret then
		ret = self.static[k]
	end
	return ret
end

function __class:__tostring(...)
	-- check for a tostring method in the class and return that 
	-- if not then just return "Class"
	if self.tostring then return self:tostring(...) end
	return tostring(className)
end
-- loop through all of the operator meta methods and attach a function using the same name
-- for custom operator overloading. for example just do
-- function aClass:add(a,b) return a.x + b.x end
for _,v in pairs({"add","sub","unm","mul","div","pow","mod","concat","eq"}) do
	__class["__"..v] = function(self, ...)
		local arg = {...}
		if self[v] then return self[v](self, self, ...) end
	end
end

-- every class has these variables
Class = {
	className="Class", 
	base={},
	static={},
	instance=false
}
Class = setmetatable(Class,__class)
function Class:printClass()
	print("["..self.className.."]")
	local indent = "    "
	for k,v in pairs(self) do
		print(indent..k, v)
	end
end

-- this is the class registering function
-- named class because of programming experience :P
function class(c, base)
	c.base = base or Class -- set the base class of the newly registered class
	c.mt = getmetatable(c.base)
	setmetatable(c, c.mt) -- set the metatable to register it as a class
end

--[[ OOP EXAMPLE USAGE CODE

Base = {test="test"}
function Base:new()
	--print("new base")
	self.name = "Base"
end
class(Base)

Player = { 
	--static={AVar="Its a static var"},
	Bounds={1,2,3,4}
 }
class(Player)
function Player:new(value)
	self.value = value
	print("new player",value)
	--self.base:new()
end
function Player:tostring()
	return tostring(self.value)
end
function Player:add(a,b)
	print(a.value,b.value)
	return a.value + b.value
end

local ply1 = Player(1)
local ply2 = Player(2)
local ply3 = Player(3)
ply2.Bounds = {9,8,7,6}
ply3.Bounds = {4,3,2,1}
--print(tostring(ply1 + ply2))
print(tostring(ply1.Bounds[1]))
print(tostring(ply2.Bounds[1]))
print(tostring(ply3.Bounds[1]))

]]--